<template>
  <div class="upload-box">
    <div>
      <span class="title">上传视频</span>
      至多1个，不大于{{ FileLimit.FileMaxSize }}M，支持格式：MP4
    </div>
    <!-- 上传器 -->
    <uploader
      ref="uploader"
      :options="options"
      :auto-start="false"
      :file-status-text="statusText"
      class="uploader-ui"
      @file-added="onFileAdded"
      @file-success="onFileSuccess"
      @file-progress="fileProgress"
      @file-error="onFileError"
    >
      <uploader-unsupport />
      <uploader-drop>
        <div>
          <uploader-btn id="global-uploader-btn" ref="uploadBtn" :attrs="attrs">
            选择文件
            <i class="el-icon-upload el-icon--right" />
          </uploader-btn>
        </div>
      </uploader-drop>
      <uploader-list />
    </uploader>
    <ul v-if="show_filename && fileListMp4" class="el-upload-list el-upload-list--text success-video">
      <li v-for="(item, i) in fileListMp4" :key="i" tabindex="0" class="el-upload-list__item is-success">
        <a class="el-upload-list__item-name">
          <i class="el-icon-video-play" />
          {{ item.filename }}
        </a>
        <label class="el-upload-list__item-status-label"><i class="el-icon-upload-success el-icon-circle-check" /></label>
        <i class="el-icon-close" @click="delMp4()" />
      </li>
    </ul>
  </div>
</template>

<script>
var SparkMD5 = require('spark-md5')
export default {
  props: {
	  uid: {
	    type: String,
	    default: ''
	  }
  },
  data() {
    return {
      fileList: [], // 上传完毕集合
      isUploadOk: true, // 是否还有未上传完成的文件
      // 视频
      FileLimit: {
        FileMaxSize: 2000, // 允许上传的大小 单位(M)
        FileFormat: ['mp4'], // 允许上传的格式
        FileUnit: 'M' // 单位
      },
      panelShow: true, // 展示上传panel
      show_filename: true, // 是否显示文件列表
      fileListMp4: [], // 视频格式数据
      uploadUrl: '', // 文件上传地址
      uploadData: '', // 文件上传参数
      options: {
        target: '', // 上传地址
        // 上传文件时文件内容的参数名，对应chunk里的Multipart对象名，upfile默认对象名为file
        fileParameterName: 'file',
        // 是否开启服务器分片校验，对应GET类型同名的target URL
        testChunks: true,
        singleFile: true, // 启用单个文件上传。上传一个文件后，第二个文件将超过现有文件，第一个文件将被取消。
        // chunkSize: '1048576' * 1, // 分块大小 单位(M)
        // 分块大小(单位：字节 2M)
        chunkSize: '2048000',
        // 失败后最多自动重试上传次数
        maxChunkRetries: 3,
        /*
		服务器分片校验函数，判断秒传及断点续传,传入的参数是Uploader.Chunk实例以及请求响应信息
		reponse码是successStatuses码时，才会进入该方法
		reponse码如果返回的是permanentErrors 中的状态码，不会进入该方法，直接进入onFileError函数 ，并显示上传失败
		reponse码是其他状态码，不会进入该方法，正常走标准上传
		checkChunkUploadedByResponse函数直接return true的话，不再调用上传接口
		*/
        checkChunkUploadedByResponse: function(chunk, response_msg) {
          const objMessage = JSON.parse(response_msg)
          if (objMessage.skipUpload) {
            return true
          }
          return (objMessage.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0
        },
        // 下面参数文件服务器验证用
        query: {
          // 传参
          merchantId: localStorage.getItem('merchantId')
        }
      },
      // 上传状态
      statusText: {
        success: '上传成功！',
        error: '出错了！',
        uploading: '上传中...',
        paused: '等待中...',
        waiting: '等待中...'
      },
      attrs: {
        accept: '.mp4' // 允许上传的格式
      },
      uploader: {},
	  uuid: ''
    }
  },
  watch: {
    uid(newValue, oldValue) {
      this.uuid = newValue
    }
  },
  created() {
    this.options.target = this.$api.gethttp() + 'uploader/chunk' // this.$api.gethttp() + 'uploader/chunk' //'http://192.168.0.109:9326/uploader/chunk'
    this.uuid = this.uid ? this.uid : this.randomString(8)
    console.log('上传路径')
    console.log(this.options.target)
    this.$nextTick(() => {
	    this.uploader = this.$refs.uploader.uploader
    })
  },
  methods: {
    // 添加一个文件时触发
    async onFileAdded(file) {
      var FileLimit = this.FileLimit
      const isFormat = this.checkExtensions(file.name, FileLimit.FileFormat) // 文件格式判断
      if (!isFormat) {
        file.ignored = true // 过滤文件
        file.cancel() // 停止上传
        return false
      }
      // 文件大小判断
      const isSize = this.checkSize(file.size)
      if (!isSize) {
        file.ignored = true // 过滤文件
        file.cancel() // 停止上传
        return false
      } else {
        this.panelShow = true // 展示上传panel
        this.show_filename = false // 不显示文件名
        this.computeMD5(file) // md5验证
      }
    },
    // 检查文件大小
    checkSize(fileSize) {
      var FileLimit = this.FileLimit
      var isSize = fileSize / 1024 / 1024 < FileLimit.FileMaxSize // 单位(M)
      if (!isSize) {
        this.$message.warning(' 文件大小不能大于' + FileLimit.FileMaxSize + FileLimit.FileUnit + '!')
        return false
      }
      return true
    },
    // extensions 允许上传的格式
    checkExtensions(fileName, extensions) {
      var format = fileName
        .split('.')
        .pop()
        .toLowerCase() // 用户上传的文件格式

      // 把允许上传文件格式的数组转为字符串
      var s = extensions.join(',')
      var exp = new RegExp(format)
      if (!exp.test(extensions)) {
        this.$message.warning('请上传 ' + s + ' 的格式!')
        return false
      }
      return true
    },

    // 文件上传中触发
    fileProgress(rootFile, file, chunk) {
      // 判断上传是否在上传
      if (file.isUploading()) {
        this.isUploadOk = false // 禁止上传
      } else {
        this.isUploadOk = true // 允许上传
      }
    },
    // 上传错误触发
    onFileError(rootFile, file, response, chunk) {
      this.$message({
        message: '上传失败,请重新上传!',
        type: 'error'
      })
	    console.log(response)
    },
    // 校验MD5
    computeMD5(file) {
      file.pause()
      const fileReader = new FileReader()
      const time = new Date().getTime()
      const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
      let currentChunk = 0
      const chunkSize = 10 * 1024 * 1000
      const chunks = Math.ceil(file.size / chunkSize)
      const spark = new SparkMD5.ArrayBuffer()
      // 由于计算整个文件的Md5太慢，因此采用只计算第1块文件的md5的方式
      const chunkNumberMD5 = 1

      loadNext()

      fileReader.onload = e => {
        spark.append(e.target.result)
        // 原来是chunks整个文件 md5
        if (currentChunk < chunkNumberMD5) {
          currentChunk++
          loadNext()
          // this.$nextTick(() => {});
        } else {
          const md5 = spark.end()
          this.computeMD5Success(md5, file)
          console.log(`MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`)
        }
      }
      fileReader.onerror = function() {
        this.error(`文件${file.name}读取出错，请检查该文件`)
        file.cancel()
      }

      function loadNext() {
        const start = currentChunk * chunkSize
        const end = start + chunkSize >= file.size ? file.size : start + chunkSize
        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end))
        console.log('计算第' + currentChunk + '块')
      }
    },
    // 验证成功
    computeMD5Success(md5, file) {
      file.uniqueIdentifier = md5 // this.randomString(32); // 把md5值作为文件的识别码
      file.resume() // 开始上传
    },
    /**
		 * e 表示长度，默认32位
		 */
    randomString(e) {
      e = e || 32
      var t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
      var a = t.length
      var n = ''
      for (var i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a))
      return n
    },
    // 视频移除
    videoRemove(file, fileList) {
      this.fileListMp4 = []
    },
    close() {
	   this.uploader.cancel()
    },
    error(msg) {
      this.$notify({
		    title: '错误',
		    message: msg,
		    type: 'error',
		    duration: 2000
      })
    },
    // 成功上传触发方法
    /*
	第一个参数 rootFile 就是成功上传的文件所属的根 Uploader.File 对象，它应该包含或者等于成功上传文件；
	第二个参数 file 就是当前成功的 Uploader.File 对象本身；
	第三个参数就是 message 就是服务端响应内容，永远都是字符串；
	第四个参数 chunk 就是 Uploader.Chunk 实例，它就是该文件的最后一个块实例，如果你想得到请求响应码的话，chunk.xhr.status就是
	*/
    onFileSuccess: function(rootFile, file, response, chunk) {
	  // refProjectId为预留字段，可关联附件所属目标，例如所属档案，所属工程等
	  file.refProjectId = this.uuid
	  if (!file.filename) {
		  file['filename'] = file.name
	  }
	  if (!file.filetype) {
	  	file['filetype'] = file.fileType
	  }
	  if (!file.identifier) {
	  	file['identifier'] = file.uniqueIdentifier
	  }
	  if (!file.totalSize) {
	  	file['totalSize'] = file.size
	  }
      this.$api.postJson('uploader/mergeFile', file, res => {
        this.$emit('onFileSuccess', res.data)
      })
	  // var res = JSON.parse(response)
      // console.log(res)
      // if (res.Result) {
      //   const fileLists = []
      //   fileLists.push(res.Data)
      //   this.fileList = fileLists
      // } else {
      //   this.$message.error(res.Errstr)
      //   return false
      // }
    }
  }
}
</script>
